#coding=utf-8
"""
将很多权限和页面的基础性功能放到这里。
lastupdated by jy 2013-04-30
"""
import datetime
from SysCommon.tools import getMD5, ShowErrorMsg
from config import safekey, domain
import config
from iLibM.loger import LogOpt, LogError


__author__ = 'jy@cjlu.edu.cn'
from tornado.web import RequestHandler
from web.utils import storage

def GetIpLong(ip):
    """
    创建IP地址的还原
    @param ip:IP地址字符串
    @return:变换后的IP地址值
    """
    ip=ip.split(".")
    if len(ip)==4:
        ip = 16777216 * long(ip[0]) + 65536 * long(ip[1]) + 256 * long(ip[2]) + long(ip[3]);
        return ip
    else:
        return 0


class basehandler(RequestHandler):

    """ 所有Handler基类 """
    def input(self):
        """
        获取到所有的输入数据，将其转换成storage方便调用
        将所有的web输入放入files和path和headers三个属性中
        """
        i= storage()#初始化一个容器
        #得到所有的输入参数和参数值
        args=self.request.arguments
        for a in args:
            i[a]=self.get_argument(a)
        i["files"]=storage(self.request.files)
        i["path"]=self.request.path
        i["headers"]=storage(self.request.headers)
        return i
    def get_request_ip(self):
        """获取请求的IP地址 """
        return self.request.remote_ip
    def get_request_ip_region(self):
        """获取请求的IP地址对应的地理位置
        """
        obj=bll_ipdb()
        ip=self.get_request_ip()
        ipl=GetIpLong(ip)
        rec=obj.GetRowByStrWhere(" (IPSTART1<="+str(ipl)+" and IPEND1>="+str(ipl)+") ")
        if rec:
            return "IP:"+ip+" 解析为:"+ rec.REGION1 + "," + rec.REGION2
        else:
            return "无记录"
    def set_login_cookies(self,user):
        """
        设置登录cookie,修订为tornado的cookies方法
        @note:cookie有效期是8小时
        """
        a=datetime.datetime.now() + datetime.timedelta(hours=8)
        self.set_cookie("ui","%d"%user.id, expires=a)
        self.set_cookie("un",user.username,None,expires=a)
        self.set_cookie("utn",user.truename,None,expires=a)
        #usercode是用来验证userid与username是否匹配的，防止用户自行修改ui和un,目前使用md5算法上可以再考虑
        self.set_cookie("usercode",getMD5(str(user.id)+user.username+safekey),None,expires=a)
    def clear_login_cookies(self):
        """
        #清理登录cookie，注销
        """
        try:
            self.set_cookie("ui","",domain,0)
            self.set_cookie("un","",domain,0)
            self.set_cookie("utn","",domain,0)
            self.set_cookie("usercode","",domain,0)
        except:
            pass
    def get_currentuser(self):
        """
        获取当前用户信息
        @return:
        """
        try:
            c=storage()
            c.ui=self.get_cookie("ui")
            c.un=self.get_cookie("un")
            c.usercode=self.get_cookie("usercode")
            if c.ui and c.un and c.usercode:
                if getMD5(c.ui+ c.un+safekey)==c.usercode:      #验证cookie有效性
                    return bll_s_user().GetUserById(c.ui)
        except Exception,ex:
            msg="登出时发生错误，具体信息:"+str(ex)
            LogError(msg)
            return None

    def checkoneuserpower(self,userobj,funno):
        """
        从系统全局中获取权限状态
        @note:此功能依赖config中的权限全局数据，请在服务启动时修改全局数据
        """
        try:
            for u in config.UserPowers:
                if u.userid==userobj.id:
                    return u["F_"+funno]
        except :
            return False
    def check_userpower(self,funno):
        """
        检查当前登录的用是否具有使用funno的权限
        """
        def getfunnamebyfunno(funno):
            """
            从系统全局中获取功能信息
            @note:依赖config中的全局权限数据
            """
            try:
                for r in config.Funs:
                    if r.funno==funno:
                        return r.funname
            except :
                return ""
        user_obj=self.get_currentuser()
        if user_obj:
            f= self.checkoneuserpower(user_obj,funno)
            if f:
                LogOpt("[%s]%s请求操作[%s][%s]功能,获授权;%s"%(user_obj.username,user_obj.truename,funno,getfunnamebyfunno(funno),self.get_request_ip_region()))
            else:
                LogOpt("[%s]%s请求操作[%s][%s]功能,被拒绝;%s"%(user_obj.username,user_obj.truename,funno,getfunnamebyfunno(funno),self.get_request_ip_region()))
            return f
        else:
            LogOpt("未登陆用户]请求[%s][%s]功能，被拒绝;%s"%(funno,getfunnamebyfunno(funno),self.get_request_ip_region()))
            return False

    def get_userpower(self,userobj):
        """
        获取当前登录用户的用户权限
        """
        if userobj:
            optobj=bll_s_ufs()
            power_status=optobj.GetUserFunsStatus(userobj)
            return power_status
        else:
            return None

def checkpower(funno):
    """
    权限检查
    调用示例:
    @checkpower("1011")
    def GET(self):
        XXX
    """
    def methodwrapper(method):
        """
        封装函数，在调用前检查权限
        """
        def newmethod(*args,**kw):
            #updated by jy 2013-04-30 发现checkpower的用途都在get或post上，那么把第一个参数self直接拿来用了。
            #不很美好，但是只能这样使用了。
            tr=args[0].check_userpower(funno)
            if tr:
                result = method(*args,**kw)
                return result
            else:
                return ShowErrorMsg("未获授权使用此功能","/logout")
        return newmethod
    return methodwrapper